home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / s / caller next >
Text File  |  1991-09-02  |  3KB  |  120 lines

  1. ; Trace back through the function call thread, and return the name of the
  2. ; function "n" calls up.
  3. ;
  4. ; e.g. if you have (in C)
  5. ;
  6. ; extern char *caller(int);
  7. ;
  8. ; void foo (void)
  9. ; {
  10. ;         bar();
  11. ; }
  12. ;
  13. ; void bar (void)
  14. ; {
  15. ;         char *f0 = caller(0);
  16. ;         char *f1 = caller(1);
  17. ; }
  18. ;
  19. ; f0 should contain "bar", and f1 should contain "foo".
  20. ;
  21. ; I tend to use caller(1) to debug things like memory problems, where I
  22. ; use things like
  23. ;
  24. ; void *xmalloc(size_t size)
  25. ; {
  26. ;         void *res = malloc(size);
  27. ;         if (res == NULL)
  28. ;         {
  29. ;                 fprintf(stderr, "Error calling malloc(%d) from %s\n",
  30. ;                         size, caller(1));
  31. ;                 exit(1);
  32. ;         }
  33. ;         return res;
  34. ; }
  35. ;
  36. ; [This use of caller(1) is OK - see below - as it is unlikely that anything
  37. ;  will call xmalloc() and not use the result somehow...]
  38. ;
  39. ;
  40. ; NOTE: This routine RELIES on the Risc-OS Arm procedure call standard
  41. ;       binding (APCS-R). In particular, it will NOT work on code
  42. ;       compiled under Ansi C v2.00 or earlier!
  43. ;
  44. ; NOTE: The parameter "n" passed to caller() is NOT always what you might
  45. ;       think! Basically, because Acorn C is very good at optimising tail-
  46. ;       recursive function calls into simple branches. For example, in the
  47. ;       example above, foo() would be optimised to a simple "B bar"
  48. ;       instruction. So f1 will, in fact, be the name of foo()'s caller (or
  49. ;       possibly even further up the calling tree!), rather than "foo".
  50. ;       In general, caller(0) is always safe, and caller(1) is OK in most
  51. ;       cases. caller(n) for n = 2 and above are more risky, basically
  52. ;       getting worse as n increases.
  53. ;
  54. ; NOTE: If you "back up" into functions compiled without function names
  55. ;       embedded in the code (eg, C library functions), caller(n) will
  56. ;       CRASH. Sorry - but there is no way that I can see to recognise
  57. ;       this situation...
  58. ;
  59. ; (Basically, the usual disclaimers all apply, in spades!).
  60. ;
  61.  
  62. a1 RN 0
  63. a2 RN 1
  64. a3 RN 2
  65. a4 RN 3
  66. v1 RN 4
  67. v2 RN 5
  68. v3 RN 6
  69. v4 RN 7
  70. v5 RN 8
  71. v6 RN 9
  72. sl RN 10
  73. fp RN 11
  74. ip RN 12
  75. sp RN 13
  76. lr RN 14
  77. pc RN 15
  78.  
  79.         AREA |Caller|, CODE, READONLY
  80.  
  81.         EXPORT  caller
  82.  
  83. 01
  84.         DCB     "caller",0
  85.         ALIGN
  86.         DCD     &FF000000 :OR: ( {PC} - %B01 )
  87.  
  88. caller
  89.         MOVS    a2, fp                 ; If frame pointer is 0 then
  90.         ADREQ   a1, null               ; there is no backtrace structure
  91.         MOVEQS  pc, lr
  92.  
  93. 02      TEQ     a1, #0                 ; Go back a1 frames...
  94.         BEQ     %F03
  95.         LDR     a2, [a2, #-12]         ; Get caller's frame pointer
  96.         TEQ     a2, #0                 ; If 0, no backtrace structure
  97.         ADREQ   a1, null
  98.         MOVEQS  pc, lr
  99.         SUB     a1, a1, #1
  100.         B       %B02
  101.  
  102. 03      LDR     a2, [a2]               ; Get caller's PC (return data save)
  103.         BIC     a2, a2, #&FC000003     ; Convert to an address
  104.         SUB     a2, a2, #12            ; Go to return data save instruction
  105.  
  106. 04      LDR     a3, [a2, #-4]!         ; Get previous word
  107.         MOV     a4, a3, LSR #24        ; Test top 8 bits
  108.         TEQ     a4, #&FF               ; If they're FF, we've found the name
  109.         BNE     %B04
  110.  
  111.         BIC     a3, a3, #&FF000000     ; Get the name offset
  112.         SUB     a1, a2, a3             ; Point to the caller's name
  113.         MOVS    pc, lr                 ; Return
  114.  
  115. null
  116.         DCB     "",0
  117.         ALIGN
  118.  
  119.         END
  120.